home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 December / macformat-019.iso / Shareware in MacFormat / Thermometer ƒ / Thermometer Source / thermo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-26  |  22.6 KB  |  1,153 lines  |  [TEXT/KAHL]

  1. /***
  2.  * thermo.c
  3.  *
  4.  *        Main source for Thermometer™.
  5.  *
  6.  *        This is based on stuff from an article in Develop magazine vol 6. 
  7.  *        by Steve Falkenberg
  8.  *
  9.  *        Copyright © 1991-1992 Bernard Bernstein. All rights reserved.
  10.  *
  11.  ***/
  12.  
  13. #if 0
  14. // this is what my GiveTime func looks like in TCPRoutines.c
  15. // it can probably go somewhere else, but this hack works.
  16. Boolean GiveTime(long sleep)
  17. {
  18.     short    ok;
  19.     EventRecord    theEvent;
  20.     static    delay = 0;
  21.     
  22.     if (!(delay++ % 10))
  23.         SpinCursor(1);
  24.  
  25.     HandleBasicEvent();
  26.  
  27.     return true;
  28. }
  29. #endif
  30.  
  31. #include <string.h>
  32. #include <MacTCPCommonTypes.h>
  33. #include <TCPPB.h>
  34. #include <Color.h>
  35. #include "CvtAddr.h"
  36. #include "TCPLow.h"
  37. #include "TCPRoutines.h"
  38. #include <CursorCtl.h>
  39. #include "thermo.h"
  40.  
  41. /* constants */
  42.  
  43. #define kBufSize    16384    /* Size for TCP stream buffer and receive buffer */
  44.  
  45. /* fuction prototypes */
  46.  
  47. OSErr Temperature(unsigned long ipAddress, unsigned long stream, short *temperature, Boolean retry);
  48.  
  49. void Initialize();
  50. void SetupThings();
  51. void MainEventLoop();
  52. void CloseThings();
  53.  
  54.  
  55. extern WindowPtr tempWindow;
  56. extern WindowPtr errWindow;
  57. extern Rect dragRect;
  58. extern Rect thermRect;
  59. short temperature;
  60. short origTemp;
  61. netPrefsRec    netPrefs;
  62. thermPrefsRec thermPrefs;
  63. unsigned long stream;
  64. unsigned long ipAddress;
  65. short    quitting = FALSE;
  66. unsigned long    nextTempUpdate = 0L;
  67. short    windowH;
  68. short    windowW;
  69. Point    windowPos;
  70. Boolean    hasWNE;
  71. RgnHandle    mouseRgn;
  72. CursHandle    waitCursor;
  73. Boolean        waiting = FALSE;
  74.  
  75.  
  76. typedef unsigned char TrapType;
  77.  
  78. /***
  79.  * TrapAvailable
  80.  *
  81.  *        Is the trap available on this machine?
  82.  ***/
  83. Boolean TrapAvailable(short tNumber, TrapType tType)
  84. {
  85. #ifndef _Unimplemented
  86. #define _Unimplemented 0xA89F
  87. #endif
  88.  
  89.     return (NGetTrapAddress(tNumber, tType) !=
  90.             GetTrapAddress(_Unimplemented));
  91. }
  92.  
  93. /***
  94.  * WNEIsImplemented
  95.  *
  96.  *        Is WaitNextEvent available on this machine?
  97.  ***/
  98. Boolean WNEIsImplemented()
  99. {
  100.     #ifndef _WaitNextEvent
  101.     #define _WaitNextEvent 0xA860
  102.     #endif
  103.     SysEnvRec    theWorld;
  104.  
  105.     SysEnvirons(1, &theWorld);
  106.     if (theWorld.machineType < 0) {
  107.         return(false);
  108.     } else {
  109.         return (TrapAvailable(_WaitNextEvent, ToolTrap));
  110.     }
  111. }    
  112.  
  113. /***
  114.  * StartWaitCursor
  115.  *
  116.  *        Change the cursor to the wait thing.
  117.  ***/
  118. StartWaitCursor()
  119. {
  120.     SetCursor(*waitCursor);
  121. }
  122.  
  123. /***
  124.  * EndWaitCursor
  125.  *
  126.  *        Change the cursor back to normal.
  127.  ***/
  128. EndWaitCursor()
  129. {
  130.     InitCursor();
  131. }
  132.  
  133. main()
  134. {
  135.     Initialize();
  136.     SetupThings();
  137.     MainEventLoop();
  138.     CloseThings();
  139. }
  140.  
  141. /***
  142.  * Initialize
  143.  *
  144.  *        Initialize stuff
  145.  ***/
  146. void Initialize()
  147. {
  148.     EventRecord event;
  149.     short        count;
  150.     SysEnvRec    mac;
  151.     acurHandle    waitCurs;
  152.     OSErr        err;
  153.     
  154.     MaxApplZone();
  155.     
  156.     InitGraf(&thePort);
  157.     InitFonts();
  158.     FlushEvents(everyEvent, 0);
  159.     InitWindows();
  160.     TEInit();
  161.     InitDialogs(NULL);
  162.     InitCursor();
  163.     mouseRgn = NewRgn();
  164.     waitCursor = GetCursor(1000);
  165.     waitCurs = (acurHandle)GetResource('acur', ACURNetWait);
  166.     InitCursorCtl(waitCurs);
  167.     
  168.     SetupErrWindow();
  169.  
  170.     if ((err = InitNetwork()) != noErr) {
  171.         PostAlert(STRInitError, err);
  172.         return;
  173.     }
  174. }
  175.  
  176. /***
  177.  * SetupThings
  178.  *
  179.  *        Setup default prefs and stuff like that
  180.  ***/
  181. void SetupThings()
  182. {
  183.     stream = 0L;
  184.  
  185.     strcpy(netPrefs.name, "thermhost");
  186.     netPrefs.port = 451;
  187.     netPrefs.interval = 10;
  188.     netPrefs.timeout = 10;
  189.     strcpy(netPrefs.search, ": ");
  190.     netPrefs.scale = farenheit;
  191.     
  192.     thermPrefs.min = -10;
  193.     thermPrefs.max = 120;
  194.     thermPrefs.scale = farenheit;
  195.  
  196.     SetUpWindow();
  197.     
  198.     windowPos = topLeft(tempWindow->portRect);
  199.     LocalToGlobal(&windowPos);
  200.     
  201.     windowH = tempWindow->portRect.bottom - tempWindow->portRect.top;
  202.     windowW = tempWindow->portRect.right - tempWindow->portRect.left;
  203.     
  204.     hasWNE = WNEIsImplemented();
  205.     RestorePrefs();
  206.     
  207.     SetUpMenus();
  208.     
  209.     MoveWindow(tempWindow, windowPos.h, windowPos.v, FALSE);
  210.     SizeWindow(tempWindow, windowW, windowH, FALSE);
  211.     ComputeThermRect();
  212.     ShowWindow(tempWindow);
  213.     
  214.     InvalRect(&tempWindow->portRect);
  215.     UpdateWindowTitle();
  216.     
  217. }
  218.  
  219. /****
  220.  * HandleMouseDown (theEvent)
  221.  *
  222.  *    Take care of mouseDown events.
  223.  *
  224.  ****/
  225. HandleMouseDown(theEvent)
  226.  
  227.     EventRecord    *theEvent;
  228.  
  229. {
  230.     WindowPtr    theWindow;
  231.     short        windowCode = FindWindow (theEvent->where, &theWindow);
  232.     
  233.     switch (windowCode)
  234.       {
  235.       case inSysWindow: 
  236.         SystemClick (theEvent, theWindow);
  237.         break;
  238.       case inMenuBar:
  239.           AdjustMenus();
  240.         HandleMenu(MenuSelect(theEvent->where));
  241.         break;
  242.       case inDrag:
  243.           DragWindow(theWindow, theEvent->where, &dragRect);
  244.           break;
  245.       case inContent:
  246.           if (theWindow != FrontWindow())
  247.               SelectWindow(theWindow);
  248.           else if (theWindow == tempWindow)
  249.                 DoWindowClick(theEvent->where);
  250.           break;
  251.       case inGoAway:
  252.           if (TrackGoAway(theWindow, theEvent->where))
  253.             HideWindow(theWindow);
  254.         break;
  255.       }
  256. }
  257. /* end HandleMouseDown */
  258.  
  259. /****
  260.  * HandleBasicEvent()
  261.  *
  262.  *        The main event dispatcher. This routine should be called
  263.  *        repeatedly (it  handles only one event).
  264.  *
  265.  *         This one happens when we are looking for a temperature.
  266.  *        This gets called from GiveTime() in TCPRoutines.c
  267.  *
  268. *****/
  269. HandleBasicEvent()
  270. {
  271.     short         ok;
  272.     EventRecord    theEvent;
  273.     unsigned long    secs;
  274.  
  275.     HiliteMenu(0);
  276.     
  277.     if (hasWNE)
  278.         ok = WaitNextEvent(everyEvent, &theEvent, 40L, mouseRgn);
  279.     else {
  280.         SystemTask ();        /* Handle desk accessories */
  281.         ok = GetNextEvent (everyEvent, &theEvent);
  282.     }
  283.     waiting = TRUE;        /* menus need to know that we are waiting */
  284.     if (ok)
  285.         switch (theEvent.what)
  286.           {
  287.         case mouseDown:
  288.             HandleMouseDown(&theEvent);
  289.             break;
  290.         case keyDown: 
  291.         case autoKey:
  292.             if ((theEvent.modifiers & cmdKey) != 0)
  293.               {
  294.               AdjustMenus();
  295.               HandleMenu(MenuKey((char) (theEvent.message & charCodeMask)));
  296.               }
  297.             break;
  298.         case updateEvt:
  299.             if ((WindowPtr)theEvent.message == tempWindow) {
  300.                 BeginUpdate(tempWindow);
  301.                 DrawTempWindow(((WindowPeek) tempWindow)->hilited);
  302.                 EndUpdate(tempWindow);
  303.             } else if ((WindowPtr)theEvent.message == errWindow) {
  304.                 BeginUpdate(errWindow);
  305.                 DrawErrWindow(((WindowPeek) errWindow)->hilited);
  306.                 EndUpdate(errWindow);
  307.             }
  308.             break;
  309.         case activateEvt:
  310.             if ((WindowPtr)theEvent.message == tempWindow) {
  311.                 InvalRect(&tempWindow->portRect);
  312.             } else if ((WindowPtr)theEvent.message == errWindow) {
  313.                 InvalRect(&errWindow->portRect);
  314.             }
  315.             break;
  316.         }
  317.     waiting = FALSE;
  318. }
  319. /* end HandleBasicEvent */
  320.  
  321.  
  322. /****
  323.  * HandleEvent()
  324.  *
  325.  *        The main event dispatcher. This routine should be called
  326.  *        repeatedly (it  handles only one event).
  327.  *
  328.  *         This one happens normally, when we are not looking for a temperature.
  329.  *
  330.  *****/
  331. HandleEvent()
  332. {
  333.     short         ok;
  334.     EventRecord    theEvent;
  335.     unsigned long    secs;
  336.  
  337.     HiliteMenu(0);
  338.     
  339.     if (hasWNE)
  340.         ok = WaitNextEvent(everyEvent, &theEvent, 40L, mouseRgn);
  341.     else {
  342.         SystemTask ();        /* Handle desk accessories */
  343.         ok = GetNextEvent (everyEvent, &theEvent);
  344.     }
  345.     if (ok)
  346.       switch (theEvent.what)
  347.         {
  348.         case mouseDown:
  349.             HandleMouseDown(&theEvent);
  350.             break;
  351.         case keyDown: 
  352.         case autoKey:
  353.             if ((theEvent.modifiers & cmdKey) != 0)
  354.               {
  355.               AdjustMenus();
  356.               HandleMenu(MenuKey((char) (theEvent.message & charCodeMask)));
  357.               }
  358.             break;
  359.         case updateEvt:
  360.             if ((WindowPtr)theEvent.message == tempWindow) {
  361.                 BeginUpdate(tempWindow);
  362.                 DrawTempWindow(((WindowPeek) tempWindow)->hilited);
  363.                 EndUpdate(tempWindow);
  364.             } else if ((WindowPtr)theEvent.message == errWindow) {
  365.                 BeginUpdate(errWindow);
  366.                 DrawErrWindow(((WindowPeek) errWindow)->hilited);
  367.                 EndUpdate(errWindow);
  368.             }
  369.             break;
  370.         case activateEvt:
  371.             if ((WindowPtr)theEvent.message == tempWindow) {
  372.                 InvalRect(&tempWindow->portRect);
  373.             } else if ((WindowPtr)theEvent.message == errWindow) {
  374.                 InvalRect(&errWindow->portRect);
  375.             }
  376.             break;
  377.         }
  378.  
  379.     /* Is it time to update the thermometer? */
  380.     GetDateTime(&secs);
  381.     if (secs > nextTempUpdate) {
  382.         nextTempUpdate = secs + netPrefs.interval  * 60;
  383.         tempUpdate();
  384.     }
  385. }
  386. /* end HandleEvent */
  387.  
  388. /***
  389.  * restartConnection
  390.  *
  391.  *        Make a new connection. Kill the old one if there was one.
  392.  ***/
  393. OSErr restartConnection()
  394. {
  395.     OSErr            err;
  396.     
  397.     if (stream != 0L)
  398.         err = ReleaseConnection(stream);
  399.     
  400.     if ((err = CvtAddr(netPrefs.name, &ipAddress)) != noErr) {
  401.         PostAlert(STRAddrError, err);
  402.         return err;
  403.     }
  404.     
  405.     if ((err = CreateStream(&stream, kBufSize)) != noErr) {
  406.         PostAlert(STRStreamError, err);
  407.         return err;
  408.     }
  409.     
  410.     err = Temperature(ipAddress, stream, &temperature, TRUE);
  411.  
  412.     if (netPrefs.scale != thermPrefs.scale) {
  413.         if (thermPrefs.scale == farenheit)
  414.             cToF(&temperature);
  415.         else
  416.             fToC(&temperature);
  417.     }
  418.     
  419.     InvalRect(&thermRect);
  420.  
  421.     return err;
  422. }
  423.  
  424. /***
  425.  * MainEventLoop
  426.  *
  427.  *        Make boson adjustment to the fibulation unit.
  428.  *:)*/
  429. void MainEventLoop()
  430. {
  431.     char            hostName[255];
  432.     OSErr            err;
  433.         
  434.     StartWaitCursor();
  435.     
  436.     if (stream == 0L)
  437.         err = restartConnection();
  438.     
  439.     while(!quitting)
  440.         HandleEvent();
  441.                     
  442.     err = ReleaseConnection(stream);
  443.     SavePrefs();
  444.     DisposeRgn(mouseRgn);
  445.     DisposeErrWindow();
  446. }
  447.  
  448. /***
  449.  * tempUpdate
  450.  *
  451.  *        update the temperature on the thermometer
  452.  ***/
  453. tempUpdate()
  454. {
  455.     OSErr    err;
  456.     
  457.     StartWaitCursor();
  458.     
  459.     err = Temperature(ipAddress, stream, &temperature, FALSE);
  460.     
  461.     if (err != noErr) {
  462.         err = ReleaseConnection(stream);
  463.         err = restartConnection();
  464.     }
  465.         
  466.     if (netPrefs.scale != thermPrefs.scale) {
  467.         if (thermPrefs.scale == farenheit)
  468.             cToF(&temperature);
  469.         else
  470.             fToC(&temperature);
  471.     }
  472.  
  473.     InvalRect(&thermRect);
  474.     EndWaitCursor();
  475. }
  476.  
  477. /***
  478.  * cToF
  479.  *
  480.  *        Celcius to Fahrenheit converter
  481.  ***/
  482. cToF(short *temp)
  483. {
  484.     short    newTemp;
  485.     newTemp = *temp * (9.0 / 5) + 32;
  486.     *temp = newTemp;
  487. }
  488.  
  489. /***
  490.  * fToC
  491.  *
  492.  *        Fahrenheit to Celcius converter
  493.  ***/
  494. fToC(short *temp)
  495. {
  496.     short    newTemp;
  497.     newTemp = (*temp - 32) * (5.0 / 9);
  498.     *temp = newTemp;
  499. }
  500.  
  501. /***
  502.  * CloseThings
  503.  *
  504.  *        Close things (hmmm, I guess not)
  505.  ***/
  506. void CloseThings()
  507. {
  508. }
  509.  
  510. /***
  511.  * Temperature
  512.  *
  513.  *        Read the temperature from the host
  514.  ***/
  515. OSErr Temperature(unsigned long ipAddress, unsigned long stream, short *temperature, Boolean retry)
  516. {
  517.     OSErr err;
  518.     long bufOffset = 0;
  519.     unsigned short dataLength;
  520.     Ptr        data;
  521.     Handle    tempData;
  522.     char    *c;
  523.     char    numStr[256];
  524.     short    numLen;
  525.     short    loc;
  526.     long    tmpTemp;
  527.     
  528.     PostAlert(STRGetting, 0);
  529.     
  530.     if ((err = OpenConnection(stream,ipAddress,netPrefs.port,netPrefs.timeout)) != noErr) {
  531.         if (retry) PostAlert(STROpenError, err);
  532.         *temperature = origTemp;
  533.         return err;
  534.     }
  535.     
  536.     tempData = NewHandle(kBufSize);
  537.     if (tempData == NULL) {
  538.         *temperature = origTemp;
  539.         CloseConnection(stream);
  540.         HandleError(memFullErr);
  541.         return memFullErr;
  542.     }
  543.     
  544.     HLock(tempData);
  545.     data = *tempData;
  546.     dataLength = kBufSize;
  547.     
  548.     while ((err = RecvData(stream,data,&dataLength,false)) == noErr) {
  549.         bufOffset += dataLength;
  550.         dataLength = kBufSize;
  551.         HUnlock(tempData);
  552.         SetHandleSize(tempData,bufOffset+kBufSize);
  553.         HLock(tempData);
  554.         data = *tempData + bufOffset;
  555.     }
  556.     
  557.     data[0] = '\0';
  558.     
  559.     HUnlock(tempData);
  560.     if (err == connectionClosing)
  561.         err = noErr;
  562.     
  563.     if (retry) HandleError(err);
  564.  
  565.     CloseConnection(stream);
  566.     
  567.     HLock(tempData);
  568.     
  569.     /* Parse the string for the temperature */
  570.     loc = find(netPrefs.search, *tempData);
  571.     if (loc < strlen(*tempData)) {
  572.         c = *tempData + loc;
  573.         numLen = strcspn(c, "\n\t\r ");
  574.         strncpy(numStr, c, numLen);
  575.         numStr[numLen] = '\0';
  576.         CtoPstr(numStr);
  577.         StringToNum(numStr, &tmpTemp);
  578.         origTemp = (short)tmpTemp;
  579.     } else {
  580.         PostAlert(STRParseError, 0);
  581.     }
  582.     
  583.     HUnlock(tempData);
  584.     DisposHandle(tempData);
  585.     
  586.     *temperature = origTemp;
  587.     
  588.     if (err == noErr)
  589.         PostAlert(STRTempOK, 0);
  590.     return err;
  591. }
  592.  
  593. /***
  594.  * find
  595.  *
  596.  *        find the given string in the source, return the offset
  597.  ***/
  598. short find(char *string, char *source)
  599. {
  600.   short i, j, length, slen, match[20], matched, found, pos;
  601.   char cc;
  602.  
  603.   length = strlen(string);
  604.   match[0] = 0;
  605.   for (i = 1; i < length; i++)
  606.     {
  607.       matched = 0;
  608.       match[i] = 0;
  609.       while (string[i + matched] == string[matched]) matched++;
  610.       for (j = 0; j < matched; j++) match[i + j] = j + 1;
  611.       if (matched) i = i + matched - 1;
  612.     }
  613.  
  614.   slen = strlen(source);
  615.   found = 0;
  616.   matched = 0;
  617.   pos = 0;
  618.   while ((pos < slen) && (!(found)))
  619.     {
  620.       cc = source[pos];
  621.           pos++;
  622.       if (cc == string[matched])
  623.                 {
  624.                   matched++;
  625.               if (matched == length) found = 1;
  626.                 }
  627.           else
  628.                 {
  629.                   if (matched != 0) pos--;
  630.               while ((matched != 0) && (cc != string[matched]))
  631.                     matched = match[matched - 1];
  632.                 }
  633.     }
  634.  
  635.   if (found) return(pos);
  636.   else return(slen);
  637. }
  638.  
  639. /***
  640.  * doAbout
  641.  *
  642.  *        display the about dlog
  643.  ***/
  644. doAbout()
  645. {
  646.     DialogPtr    theDlg;
  647.     short        theItem;
  648.  
  649.     theDlg = GetNewDialog(DLOGAbout, NULL, -1L);
  650.     ModalDialog(NULL, &theItem);
  651.     DisposDialog(theDlg);
  652. }
  653.  
  654. /***
  655.  * changeThermPrefs
  656.  *
  657.  *        Change the thermometer prefs: range, C/F
  658.  *        just redraw the thermometer with done
  659.  ***/
  660. changeThermPrefs()
  661. {
  662.     if (getThermPrefs(&thermPrefs)) {
  663.         tempUpdate();
  664.         InvalRect(&tempWindow->portRect);
  665.     }
  666. }
  667.  
  668. /***
  669.  * changeNetPrefs
  670.  *
  671.  *        Change the network prefs: host addr, port, etc.
  672.  *        restart connection when done
  673.  ***/
  674. changeNetPrefs()
  675. {
  676.     if (getNetPrefs(&netPrefs)) {
  677.         StartWaitCursor();
  678.         restartConnection();
  679.         EndWaitCursor();
  680.         InvalRect(&tempWindow->portRect);
  681.     }
  682. }
  683.  
  684. /***
  685.  * getNetPrefs
  686.  *
  687.  *        Get the net prefs from the dialog
  688.  ***/
  689. getNetPrefs(netPrefsRec *prefs)
  690. {
  691.     DialogPtr    dlg;
  692.     short        item;
  693.     Boolean        done = FALSE;
  694.     Boolean        changed;
  695.     
  696.     dlg = GetNewDialog(DLOGNetwork, NULL, -1L);
  697.     SetupNetItems(dlg, prefs);
  698.     do {
  699.         ModalDialog(NULL, &item);
  700.         switch(item) {
  701.             case DItmOK:
  702.                 FillNetPrefs(dlg, prefs);
  703.                 done = TRUE;
  704.                 changed = TRUE;
  705.                 break;
  706.             case DItmCancel:
  707.                 done = TRUE;
  708.                 changed = FALSE;
  709.                 break;
  710.             case DItmNCel:
  711.                 CheckForC(dlg, DItmNCel, DItmNFah, celcius);
  712.                 break;
  713.             case DItmNFah:
  714.                 CheckForC(dlg, DItmNCel, DItmNFah, farenheit);
  715.                 break;
  716.         }
  717.     } while (!done);
  718.     DisposDialog(dlg);
  719.     return changed;
  720. }    
  721.  
  722. /***
  723.  * FillNetPrefs
  724.  *
  725.  *        Fill the record with stuff from the dlog
  726.  ***/
  727. FillNetPrefs(DialogPtr dlg, netPrefsRec *prefs)
  728. {
  729.     short    itemType;
  730.     Handle    itemHdl;
  731.     Rect    itemBox;
  732.     Str255    tmpString;
  733.     long    tmpNum;
  734.  
  735.     GetDItem(dlg, DItmAddr, &itemType, &itemHdl, &itemBox);
  736.     GetIText(itemHdl, &tmpString);
  737.     PtoCstr((char*)tmpString);
  738.     strcpy(prefs->name, (char*)tmpString);
  739.  
  740.     GetDItem(dlg, DItmPort, &itemType, &itemHdl, &itemBox);
  741.     GetIText(itemHdl, &tmpString);
  742.     StringToNum(tmpString, &tmpNum);
  743.     prefs->port = (short)tmpNum;
  744.  
  745.     GetDItem(dlg, DItmTimeout, &itemType, &itemHdl, &itemBox);
  746.     GetIText(itemHdl, &tmpString);
  747.     StringToNum(tmpString, &tmpNum);
  748.     prefs->timeout = (short)tmpNum;
  749.     
  750.     GetDItem(dlg, DItmTime, &itemType, &itemHdl, &itemBox);
  751.     GetIText(itemHdl, &tmpString);
  752.     StringToNum(tmpString, &tmpNum);
  753.     prefs->interval = (short)tmpNum;
  754.     
  755.     GetDItem(dlg, DItmSearch, &itemType, &itemHdl, &itemBox);
  756.     GetIText(itemHdl, &tmpString);
  757.     PtoCstr((char*)tmpString);
  758.     strcpy(prefs->search, (char*)tmpString);
  759.  
  760.     GetForC(dlg, DItmNCel, DItmNFah, &prefs->scale);
  761. }
  762.  
  763. /***
  764.  * SetupNetItems
  765.  *
  766.  *        Setup the net prefs dlog from the rec
  767.  ***/
  768. SetupNetItems(DialogPtr dlg, netPrefsRec *prefs)
  769. {
  770.     short    itemType;
  771.     Handle    itemHdl;
  772.     Rect    itemBox;
  773.     Str255    tmpString;
  774.     
  775.     strcpy((char*)tmpString, prefs->name);
  776.     CtoPstr((char*)tmpString);
  777.     GetDItem(dlg, DItmAddr, &itemType, &itemHdl, &itemBox);
  778.     SetIText(itemHdl, tmpString);
  779.  
  780.     NumToString((long)prefs->port, tmpString);
  781.     GetDItem(dlg, DItmPort, &itemType, &itemHdl, &itemBox);
  782.     SetIText(itemHdl, tmpString);
  783.     
  784.     NumToString((long)prefs->interval, tmpString);
  785.     GetDItem(dlg, DItmTime, &itemType, &itemHdl, &itemBox);
  786.     SetIText(itemHdl, tmpString);
  787.  
  788.     NumToString((long)prefs->timeout, tmpString);
  789.     GetDItem(dlg, DItmTimeout, &itemType, &itemHdl, &itemBox);
  790.     SetIText(itemHdl, tmpString);
  791.  
  792.     strcpy((char*)tmpString, prefs->search);
  793.     CtoPstr((char*)tmpString);
  794.     GetDItem(dlg, DItmSearch, &itemType, &itemHdl, &itemBox);
  795.     SetIText(itemHdl, tmpString);
  796.  
  797.     CheckForC(dlg, DItmNCel, DItmNFah, prefs->scale);
  798.     
  799.     SelIText(dlg, DItmAddr, 0, 32767);
  800. }
  801.  
  802. /***
  803.  * getThermPrefs
  804.  *
  805.  *        Get the thermo prefs from the dialog
  806.  ***/
  807. getThermPrefs(thermPrefsRec *prefs)
  808. {
  809.     DialogPtr    dlg;
  810.     short        item;
  811.     Boolean        done = FALSE;
  812.     Boolean        changed;
  813.     
  814.     dlg = GetNewDialog(DLOGTherm, NULL, -1L);
  815.     SetupThermItems(dlg, prefs);
  816.     do {
  817.         ModalDialog(NULL, &item);
  818.         switch(item) {
  819.             case DItmOK:
  820.                 FillThermPrefs(dlg, prefs);
  821.                 done = TRUE;
  822.                 changed = TRUE;
  823.                 break;
  824.             case DItmCancel:
  825.                 done = TRUE;
  826.                 changed = FALSE;
  827.                 break;
  828.             case DItmTCel:
  829.                 CheckForC(dlg, DItmTCel, DItmTFah, celcius);
  830.                 break;
  831.             case DItmTFah:
  832.                 CheckForC(dlg, DItmTCel, DItmTFah, farenheit);
  833.                 break;
  834.         }
  835.     } while (!done);
  836.     DisposDialog(dlg);
  837.     return changed;
  838. }    
  839.  
  840. /***
  841.  * FillThermPrefs
  842.  *
  843.  *        Fill the therm prefs record from the dialog
  844.  ***/
  845. FillThermPrefs(DialogPtr dlg, thermPrefsRec *prefs)
  846. {
  847.     short    itemType;
  848.     Handle    itemHdl;
  849.     Rect    itemBox;
  850.     Str255    tmpString;
  851.     long    tmpNum;
  852.  
  853.     GetDItem(dlg, DItmMin, &itemType, &itemHdl, &itemBox);
  854.     GetIText(itemHdl, &tmpString);
  855.     StringToNum(tmpString, &tmpNum);
  856.     prefs->min = (short) tmpNum;
  857.  
  858.     GetDItem(dlg, DItmMax, &itemType, &itemHdl, &itemBox);
  859.     GetIText(itemHdl, &tmpString);
  860.     StringToNum(tmpString, &tmpNum);
  861.     prefs->max = (short) tmpNum;
  862.  
  863.     GetForC(dlg, DItmTCel, DItmTFah, &prefs->scale);
  864.     UpdateWindowTitle();
  865.  
  866. }
  867.  
  868. /***
  869.  * SetupThermItems
  870.  *
  871.  *        Fill the therm prefs dlog from the rec
  872.  ***/
  873. SetupThermItems(DialogPtr dlg, thermPrefsRec *prefs)
  874. {
  875.     short    itemType;
  876.     Handle    itemHdl;
  877.     Rect    itemBox;
  878.     Str255    tmpString;
  879.     
  880.     NumToString((long)prefs->min, tmpString);
  881.     GetDItem(dlg, DItmMin, &itemType, &itemHdl, &itemBox);
  882.     SetIText(itemHdl, tmpString);
  883.  
  884.     NumToString((long)prefs->max, tmpString);
  885.     GetDItem(dlg, DItmMax, &itemType, &itemHdl, &itemBox);
  886.     SetIText(itemHdl, tmpString);
  887.  
  888.     CheckForC(dlg, DItmTCel, DItmTFah, prefs->scale);
  889.     
  890.     SelIText(dlg, DItmMin, 0, 32767);
  891. }
  892.  
  893. /***
  894.  * CheckForC
  895.  *
  896.  *        That is Check F or C (fahrenheit or celcius) (radio buttons)
  897.  ***/
  898. CheckForC(DialogPtr dlg, short cItem, short fItem, ForC scale)
  899. {
  900.     short    itemType;
  901.     Handle    itemHdl;
  902.     Rect    itemBox;
  903.  
  904.     GetDItem(dlg, cItem, &itemType, &itemHdl, &itemBox);
  905.     SetCtlValue(itemHdl, scale == celcius);
  906.  
  907.     GetDItem(dlg, fItem, &itemType, &itemHdl, &itemBox);
  908.     SetCtlValue(itemHdl, scale == farenheit);
  909. }
  910.  
  911.  
  912. /***
  913.  * GetForC
  914.  *
  915.  *        That is Get F or C (fahrenheit or celcius) (radio buttons)
  916.  ***/
  917. GetForC(DialogPtr dlg, short cItem, short fItem, ForC *scale)
  918. {
  919.     short    itemType;
  920.     Handle    itemHdl;
  921.     Rect    itemBox;
  922.     Boolean    isThisOne;
  923.     
  924.     GetDItem(dlg, cItem, &itemType, &itemHdl, &itemBox);
  925.     if (GetCtlValue(itemHdl))
  926.         *scale = celcius;
  927.     else
  928.         *scale = farenheit;
  929.         
  930. }
  931.  
  932. /***
  933.  * SavePrefs
  934.  *
  935.  *        Save prefs file with net and thermo prefs
  936.  ***/
  937. SavePrefs()
  938. {
  939.     StringHandle    fileHdl;
  940.     StringHandle    folderName;
  941.     OSErr            err;
  942.     SysEnvRec        envRec;
  943.     short            refNum;
  944.     short            volNum;
  945.     long            dirID;
  946.     long            procID;
  947.     Str255            fileName;
  948.     prefsFileRec    prefRec;
  949.     long            count;
  950.     GrafPtr            savePort;
  951.     short            sVolNum;
  952.     long            sDirID, sProcID;
  953.     CInfoPBRec        pb;
  954.     
  955.     
  956.     GetPort(&savePort);
  957.     SetPort(tempWindow);
  958.     
  959.     windowPos = topLeft(tempWindow->portRect);
  960.     windowH = tempWindow->portRect.bottom - tempWindow->portRect.top;
  961.     windowW = tempWindow->portRect.right - tempWindow->portRect.left;
  962.     LocalToGlobal(&windowPos);
  963.     
  964.     SysEnvirons(1, &envRec);
  965.     
  966.     folderName = GetString(STRPrefsFolder);
  967.     if (folderName == NULL) {
  968.         HandleError(ResError());
  969.         return;
  970.     }
  971.     err = GetWDInfo(envRec.sysVRefNum, &volNum, &sDirID, &sProcID);
  972.     if (err != noErr) {
  973.         HandleError(err);
  974.         return;
  975.     }
  976.     pb.dirInfo.ioCompletion = NULL;
  977.     pb.dirInfo.ioNamePtr = *folderName;
  978.     pb.dirInfo.ioVRefNum = volNum;
  979.     pb.dirInfo.ioFDirIndex = 0;
  980.     pb.dirInfo.ioDrDirID = sDirID;
  981.     err = PBGetCatInfo(&pb, FALSE);
  982.     if (err == fnfErr) {
  983.         err = DirCreate(sVolNum, sDirID, *folderName, &dirID);
  984.     } else if (err == noErr) {
  985.         dirID = pb.dirInfo.ioDrDirID;
  986.     } else {
  987.         HandleError(err);
  988.         return;
  989.     }
  990.  
  991.     
  992.     fileHdl = GetString(STRPrefsName);
  993.     if (fileHdl == NULL) {
  994.         HandleError(ResError());
  995.         return;
  996.     }
  997.  
  998.     BlockMove(*fileHdl, fileName, *fileHdl[0] + 1);
  999.         
  1000.     err = HOpen(volNum, dirID, fileName, fsWrPerm, &refNum);
  1001.     if (err == fnfErr) {
  1002.         err = HCreate(volNum, dirID, fileName, CREATOR, PREFTYPE);
  1003.         err = HOpen(volNum, dirID, fileName, fsWrPerm, &refNum);
  1004.         if (err != noErr) {
  1005.             HandleError(err);
  1006.             return;
  1007.         }
  1008.     } else if (err != noErr) {
  1009.         HandleError(err);
  1010.         return;
  1011.     }
  1012.     
  1013.     prefRec.version = PREFVERSION;
  1014.     BlockMove(&netPrefs, &prefRec.netPrefs, sizeof(netPrefs));
  1015.     BlockMove(&thermPrefs, &prefRec.thermPrefs, sizeof(thermPrefs));
  1016.     prefRec.windowPos = windowPos;
  1017.     prefRec.width = windowW;
  1018.     prefRec.height = windowH;
  1019.     count = sizeof(prefRec);
  1020.     err = FSWrite(refNum, &count, &prefRec);
  1021.     err = FSClose(refNum);
  1022.     SetPort(savePort);
  1023. }
  1024.  
  1025.  
  1026. /***
  1027.  * RestorePrefs
  1028.  *
  1029.  *        Read prefs from the prefs file and file records
  1030.  ***/
  1031. RestorePrefs()
  1032. {
  1033.     StringHandle    strHdl;
  1034.     StringHandle    folderName;
  1035.     OSErr            err;
  1036.     SysEnvRec        envRec;
  1037.     short            refNum;
  1038.     short            volNum;
  1039.     long            dirID;
  1040.     long            procID;
  1041.     long            sDirID, sProcID;
  1042.     Str255            fileName;
  1043.     prefsFileRec    prefRec;
  1044.     long            count;
  1045.     RgnHandle        rgn;
  1046.     Rect            windowRect;
  1047.     CInfoPBRec        pb;
  1048.     
  1049.         
  1050.     SysEnvirons(1, &envRec);
  1051.     
  1052.     folderName = GetString(STRPrefsFolder);
  1053.     if (folderName == NULL) {
  1054.         HandleError(ResError());
  1055.         return;
  1056.     }
  1057.     err = GetWDInfo(envRec.sysVRefNum, &volNum, &sDirID, &sProcID);
  1058.     if (err != noErr) {
  1059.         HandleError(err);
  1060.         return;
  1061.     }
  1062.     pb.dirInfo.ioCompletion = NULL;
  1063.     pb.dirInfo.ioNamePtr = *folderName;
  1064.     pb.dirInfo.ioVRefNum = volNum;
  1065.     pb.dirInfo.ioFDirIndex = 0;
  1066.     pb.dirInfo.ioDrDirID = sDirID;
  1067.     err = PBGetCatInfo(&pb, FALSE);
  1068.     if (err == fnfErr) {
  1069.         err = DirCreate(volNum, sDirID, *folderName, &dirID);
  1070.     } else if (err == noErr) {
  1071.         dirID = pb.dirInfo.ioDrDirID;
  1072.     } else {
  1073.         HandleError(err);
  1074.         return;
  1075.     }
  1076.  
  1077.     strHdl = GetString(STRPrefsName);
  1078.     if (strHdl == NULL) {
  1079.         HandleError(ResError());
  1080.         return;
  1081.     }
  1082.  
  1083.     BlockMove(*strHdl, fileName, *strHdl[0] + 1);
  1084.     
  1085.     err = HOpen(volNum, dirID, fileName, fsWrPerm, &refNum);
  1086.     if (err == fnfErr) {
  1087.         changeNetPrefs();
  1088.         return;
  1089.     } else if (err != noErr) {
  1090.         HandleError(err); 
  1091.         return;
  1092.     }
  1093.  
  1094.     count = sizeof(prefRec);
  1095.     err = FSRead(refNum, &count, &prefRec);
  1096.     err = FSClose(refNum);
  1097.     
  1098.     if (prefRec.version != PREFVERSION) 
  1099.         return;
  1100.     
  1101.     BlockMove(&prefRec.netPrefs, &netPrefs, sizeof(netPrefs));
  1102.     BlockMove(&prefRec.thermPrefs, &thermPrefs, sizeof(thermPrefs));
  1103.     
  1104.     topLeft(windowRect) = prefRec.windowPos;
  1105.     windowRect.right = windowRect.left + prefRec.width;
  1106.     windowRect.bottom = windowRect.top + prefRec.height;
  1107.     
  1108.     rgn = GetGrayRgn();
  1109.     if (RectInRgn(&windowRect, rgn)) {
  1110.         windowPos = prefRec.windowPos;
  1111.         windowH = prefRec.height;
  1112.         windowW = prefRec.width;
  1113.     }
  1114. }
  1115.  
  1116. /***
  1117.  * HandleError
  1118.  *
  1119.  *        Post the error alert
  1120.  ***/
  1121. HandleError(OSErr err)
  1122. {
  1123.     short    errStringID;
  1124.     
  1125.     if (err != noErr) {
  1126.         if (err <= -23000 && err >= -23048)
  1127.             errStringID = STRNetError;
  1128.         else
  1129.             errStringID = STRAnyError;
  1130.         PostAlert(errStringID, err);
  1131.     }
  1132. }
  1133.  
  1134. /***
  1135.  * PostAlert
  1136.  *
  1137.  *        This used to display an alert, but now it just updates the message
  1138.  *        window. Who cares if the temperature did not get updated recently?
  1139.  *        You can always look at the status window to see if it is current.
  1140.  ***/
  1141. PostAlert(short stringID, OSErr errNum)
  1142. {
  1143.     Str255    errString;
  1144.     unsigned char    errNumString[30];
  1145.     unsigned char    timeString[30];
  1146.     unsigned char    dateString[128];
  1147.     long    seconds;
  1148.     
  1149.     GetIndString(errString, STRErrors, stringID);
  1150.     
  1151.     DisplayMessage(errString);
  1152. }
  1153.